﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using MultWebApi.Models;
using System.Security.Claims;

namespace MultWebApi.SalesWebApi.Auth
{
    public class UserCheckControllerFilter : ActionFilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var user = context.HttpContext.User;

            if (!user.Identity.IsAuthenticated)
            {
                // it isn't needed to set unauthorized result 
                // as the base class already requires the user to be authenticated
                // this also makes redirect to a login page work properly
                // context.Result = new UnauthorizedResult();
                return;
            }
            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
            var allowPers = controllerActionDescriptor.MethodInfo.GetCustomAttributes(typeof(UserCheckAttribute), false).ToList();
            bool isAuthorized = false;
            if (allowPers.Count > 0)
            {
                var sysItem = user.Claims.FirstOrDefault(p => p.Type == ClaimTypes.Spn);
                int userSys = 0;
                if (sysItem != null)
                {
                    userSys = ConvertHelper.ToInt32(sysItem.Value);
                }
                string userAction = string.Empty;
                var actItem = user.Claims.FirstOrDefault(p => p.Type == ClaimTypes.System);
                if (actItem != null)
                {
                    userAction = actItem.Value;
                }
                isAuthorized = true;
                foreach (var item in allowPers)
                {
                    var checkAtt = item as UserCheckAttribute;
                    if (checkAtt != null)
                    {
                        if (checkAtt.SystemFlag > 0 && (userSys & checkAtt.SystemFlag) == 0)
                        {
                            isAuthorized = false;
                        }
                        if (!string.IsNullOrEmpty(checkAtt.Action) && checkAtt.Action == "Inner" && checkAtt.Action != userAction)
                        {
                            isAuthorized = false;
                        }
                    }
                }
            }
            if (!isAuthorized)
            {
                var rst = new DataResult();
                rst.ErrorCode = SysErrorCode.KAuthFail;
                rst.Message = SysErrorCode.GetErrorMessge(rst.ErrorCode);
                context.Result = new JsonResult(rst);
            }
            return;

        }
    }
    public class PolicyRequirement : IAuthorizationRequirement
    {

    }

    public class PermissionCheckPolicyHandler : AuthorizationHandler<PolicyRequirement>
    {
        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext authoriazationContext,
            PolicyRequirement requirement)
        {
            if (authoriazationContext.User == null || !authoriazationContext.User.Identity.IsAuthenticated)
            {
                authoriazationContext.Fail();
                return;
            }

            var responseContext = authoriazationContext.Resource as DefaultHttpContext;
            /*
            #region 请求auth验证
            var token = responseContext.HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
            var fact = responseContext.HttpContext.RequestServices.GetService<IHttpClientFactory>();
            if (fact != null)
            {
                var httpClient = fact.CreateClient("AuthApi");
                var url = string.Format("{0}Account/Check?token={1}", httpClient.BaseAddress, token);
                var httpRst = await httpClient.PostAsync(url, null);
                if (httpRst.IsSuccessStatusCode)
                {
                    var resultObj = httpRst.Content.ReadAsStringAsync().Result;
                    var rst = Newtonsoft.Json.JsonConvert.DeserializeObject<DataResult>(resultObj);
                    if (rst == null || rst.ErrorCode != SysErrorCode.KSuccess)
                    {
                        authoriazationContext.Fail();
                        return;
                    }
                }
                else
                {
                    authoriazationContext.Fail();
                    return;
                }
            }
            #endregion
            */
            var expTime = authoriazationContext.User.FindFirst(ClaimTypes.Expiration);
            if (expTime != null)
            {
                DateTime expireTime = ConvertHelper.ToLongDateTime(expTime.Value);
                if (DateTime.Now.CompareTo(expireTime.AddHours(-4)) > 0)
                {
                    responseContext.Response.Headers["RefreshToken"] = "true";
                }
            }
            authoriazationContext.Succeed(requirement);
            return;
        }
    }
}
